package com.tarry.queue;

import lombok.extern.slf4j.Slf4j;

/**
 *  使用数组实现队列
 */
@Slf4j
public class ArrayQueue<T> {
    //队列容量
    private int capacity;
    //队列出队指针
    private int head;
    //队列入队指针
    private int tail;
    private Object[] data;

    public ArrayQueue(int capacity){
        this.capacity = capacity;
        this.data = new Object[this.capacity];
        this.head = 0;
        this.tail = 0;
    }

    private boolean isFull() {
        return this.capacity == this.tail;
    }

    private boolean isEmpty() {
        return this.head == this.tail;
    }

    /**
     * 入队操作
     * <br>
     * <p>
     *     当入队指针=队列容量，且出队指针不为0时，说明当前队列不为满队列，
     *  此时进入入队操作时，先将队列原数据进行迁移，保证新入队队数据能正常入队。
     * </p>
     * @param item 入队数据
     * @return true or false
     */
    public boolean enQueue(T item){
        if (this.isFull()) {
            // 表示队列已经满了不能存放新的数据
            if (this.head == 0) {
                log.warn("the queue is full !");
                return false;
            }
            // 进行数据搬移
            if (this.tail - this.head >= 0)
                System.arraycopy(this.data, this.head, this.data, 0, this.tail - this.head);
            // 搬移完之后更新head和tail
            this.tail -= this.head ;
            this.head = 0;
        }
        // 插入数据
        this.data[this.tail] = item;
        this.tail ++ ;
        return true;
    }


    /**
     *  出队列：
     *  <br>
     *  <p>
     *   当前存在，出队列后，所属内存块未被释放，不能再做入队操作
     *  </p>
     * @return
     */
    public T deQueue() {
        if (this.isEmpty()) {
            log.warn("queue is empty !");
            return null;
        }
        T item = (T) this.data[this.head];
        this.head ++ ;
        return item;
    }

    public void showQueue(){
        if (this.isEmpty()) {
            log.warn("queue is empty !");
            return;
        }
        for (int i = this.head; i < this.tail; i++) {
            System.out.println("queue["+ (i + 1) +"]=" + this.data[i]);
        }
    }


}

